﻿#include "CModule.h"
#include "CSem.h"
#include "CSem.h"
#include "CThread.h"
#include "CMsg.h"
#include <string.h>
#include <stdlib.h>

#pragma warning(disable:4996)

static void md_common_entry(void* param) {
	CModule* thes = (CModule*)param;
	while (1) {
		CMsg* msg = 0;
		thes->sem.wait(&thes->sem);
		msg = thes->q.pop(&thes->q);
		if (msg) {
			thes->exeMsg(thes, msg);
			free(msg);
		} else {
			//on err. do something
		}		
	}
}

static int md_run(struct _cmodule_* md, void(*entry)(void *)) {
	if (USE_DEFAULT_MODULE_ENTRY == entry) {
		md->th.run(&md->th, md_common_entry, md);
	} else {
		md->th.run(&md->th, entry, md);
	}	
	return 0;
}

static int sendMsg(struct _cmodule_* md, CMsg* msg) {
	CMsg* heap_msg = (CMsg*)malloc(sizeof(CMsg) + msg->data_len);
	memcpy(heap_msg, msg, sizeof(CMsg) + msg->data_len);
	md->q.push(&md->q, heap_msg);
	md->sem.signal(&md->sem);
	return 0;
}

static int cmodule_exeMsg(CModule* thes, CMsg* msg) {
    XMap* m = &thes->msgid_func_map;
    MODULE_EXEMSG_FN fn = (MODULE_EXEMSG_FN)m->find(m, (void*)msg->msg_id);
    if(fn) {
        (*fn)(thes, msg);
    } else {
        //error log output
    }
    return 0;
}

int construct_module(CModule* thes, const char* module_name) {
	construct_queue(&thes->q, 1);
	construct_sem(&thes->sem, 0);
	construct_thread(&thes->th);
    construct_map(&thes->msgid_func_map, INT_KEY_CMP_FUNC);
	if (strlen(module_name) > MODULE_NAME_MAX) {
		memcpy(thes->module_name, module_name, MODULE_NAME_MAX);
		thes->module_name[MODULE_NAME_MAX] = '\0';
	} else {
		strcpy(thes->module_name, module_name);
	}

	thes->run = md_run;
	thes->sendMsg = sendMsg;
	thes->exeMsg = cmodule_exeMsg;
	return 0;
}